package com.hospital.workstation.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hospital.common.constant.Constants;
import com.hospital.common.core.domain.R;
import com.hospital.common.core.domain.entity.SysDept;
import com.hospital.common.core.domain.entity.SysDictData;
import com.hospital.common.core.domain.entity.SysUser;
import com.hospital.common.core.domain.model.LoginUser;
import com.hospital.common.helper.DataBaseHelper;
import com.hospital.common.helper.LoginHelper;
import com.hospital.common.utils.StreamUtils;
import com.hospital.common.utils.StringUtils;
import com.hospital.common.core.page.TableDataInfo;
import com.hospital.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hospital.system.mapper.SysDeptMapper;
import com.hospital.system.mapper.SysDictDataMapper;
import com.hospital.system.mapper.SysUserMapper;
import com.hospital.workstation.constant.DictConstants;
import com.hospital.workstation.domain.*;
import com.hospital.workstation.domain.bo.HisChangeDepartmentBo;
import com.hospital.workstation.domain.vo.HisAdmittingDiagInfoVo;
import com.hospital.workstation.mapper.*;
import com.hospital.workstation.service.IFirstLevelService;
import com.hospital.workstation.service.IHisChangeDepartmentService;
import com.hospital.workstation.utils.CXFClientUtil;
import com.hospital.workstation.utils.CareLevelUtil;
import com.hospital.workstation.utils.MD5Util;
import com.hospital.workstation.utils.PoiTlUtils;
import com.hospital.workstation.webService.domain.Request;
import com.hospital.workstation.webService.domain.Response;
import lombok.RequiredArgsConstructor;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.map.ListOrderedMap;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.stereotype.Service;
import com.hospital.workstation.domain.bo.PatientBaseInfoBo;
import com.hospital.workstation.domain.vo.PatientBaseInfoVo;
import com.hospital.workstation.service.IPatientBaseInfoService;

import java.lang.reflect.WildcardType;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 患者基本信息Service业务层处理
 *
 * @author whb
 * @date 2023-02-08
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class PatientBaseInfoServiceImpl implements IPatientBaseInfoService {

    private final PatientBaseInfoMapper baseMapper;
    private final SysDictDataMapper dictDataMapper;
    private final SysDeptMapper deptMapper;
    private final IHisChangeDepartmentService hisChangeDepartmentService;
    private final SysUserMapper sysUserMapper;
    private final FirstLevelMapper firstLevelMapper;
    private final TwoLevelMapper twoLevelMapper;
    private final GradingFirstMapper gradingFirstMapper;
    private final GradingTwoMapper gradingTwoMapper;
    private final HisAdmittingDiagInfoMapper diagInfoMapper;

    /**
     * 查询患者基本信息
     */
    @Override
    public PatientBaseInfoVo queryById(Long id) {
        // 查询患者住院信息
        PatientBaseInfoVo patientBaseInfoVo = baseMapper.selectVoById(id);
        // 计算MD5运算得到签名字符串
        if (ObjectUtil.isNotNull(patientBaseInfoVo)) {
            if (StringUtils.isNotBlank(patientBaseInfoVo.getMedicareNo())
                && StringUtils.isNotBlank(patientBaseInfoVo.getVisitTimes())
                && StringUtils.isNotBlank(patientBaseInfoVo.getMedicareWardCode())) {
                String sign = MD5Util.getMd5(patientBaseInfoVo.getMedicareNo(), patientBaseInfoVo.getVisitTimes(), patientBaseInfoVo.getMedicareWardCode());
                patientBaseInfoVo.setSign(sign);
            }
        }
        // 查询或创建一级监护分级信息
        GradingFirst gradingFirst = gradingFirstMapper.selectOne(new LambdaQueryWrapper<GradingFirst>().eq(GradingFirst::getMedicalRecordNo, patientBaseInfoVo.getMedicalRecordNo()));
        if (ObjectUtil.isNull(gradingFirst)) {
            gradingFirst = new GradingFirst();
            gradingFirst.setMedicalRecordNo(patientBaseInfoVo.getMedicalRecordNo());
            gradingFirstMapper.insert(gradingFirst);
        }
        // 删除病历号重复的一级监护分级信息
        List<GradingFirst> gradingFirstList = gradingFirstMapper.selectList(new LambdaQueryWrapper<GradingFirst>().eq(GradingFirst::getMedicalRecordNo, patientBaseInfoVo.getMedicalRecordNo()));
        if (gradingFirstList.size() == 2) {
            gradingFirstMapper.deleteById(gradingFirstList.get(1));
        }
        // 查询或创建二级监护分级信息
        GradingTwo gradingTwo = gradingTwoMapper.selectOne(new LambdaQueryWrapper<GradingTwo>().eq(GradingTwo::getMedicalRecordNo, patientBaseInfoVo.getMedicalRecordNo()));
        if (ObjectUtil.isNull(gradingTwo)) {
            gradingTwo = new GradingTwo();
            gradingTwo.setMedicalRecordNo(patientBaseInfoVo.getMedicalRecordNo());
            gradingTwoMapper.insert(gradingTwo);
        }
        // 删除病历号重复的二级监护分级信息
        List<GradingTwo> gradingTwoList = gradingTwoMapper.selectList(new LambdaQueryWrapper<GradingTwo>().eq(GradingTwo::getMedicalRecordNo, patientBaseInfoVo.getMedicalRecordNo()));
        if (gradingTwoList.size() == 2) {
            gradingTwoMapper.deleteById(gradingTwoList.get(1));
        }
        // 判断患者的监护级别
        PatientBaseInfo patientBaseInfo = BeanUtil.toBean(patientBaseInfoVo, PatientBaseInfo.class);
        // 一级监护
        boolean isFirstGrading = CareLevelUtil.isFirstGrading(gradingFirst);
        if (isFirstGrading) {
            patientBaseInfo.setGuardianLevel(DictConstants.GUARDIAN_LEVEL_THREE);
            patientBaseInfoVo.setGuardianLevel(DictConstants.GUARDIAN_LEVEL_THREE);
        }
        // 二级监护
        boolean isTwoGrading = CareLevelUtil.isTwoGrading(gradingTwo);
        if (!isFirstGrading && isTwoGrading) {
            patientBaseInfo.setGuardianLevel(DictConstants.GUARDIAN_LEVEL_TWO);
            patientBaseInfoVo.setGuardianLevel(DictConstants.GUARDIAN_LEVEL_TWO);
        }
        // 三级监护
        if (!isFirstGrading && !isTwoGrading) {
            patientBaseInfo.setGuardianLevel(DictConstants.GUARDIAN_LEVEL_ONE);
            patientBaseInfoVo.setGuardianLevel(DictConstants.GUARDIAN_LEVEL_ONE);
        }
        // 调用护理信息
        if (patientBaseInfo.getPatientWeight() == null || patientBaseInfo.getPatientHeight() == null) {
            // 主动查询HIS中的第一次生命体征接口
            // 封装参数
            Map<String, Object> params = new HashMap<>();
            params.put("code", "MES0183");
            params.put("xml", new Response().getMES0183Xml(patientBaseInfoVo.getPaadmVisitNo()));
            // 解析返回字符串
            // String hipMessageInfo = new Response().getVitalSignInfo();
            String hipMessageInfo = CXFClientUtil.sendXml("HIPMessageInfo", params);
            Request vitalSignInfoRequest = CXFClientUtil.getRequest(hipMessageInfo);
            Map vitalSignInfoBody = vitalSignInfoRequest.getBody();
            List<Map> vitalSignInfoList = null;
            Map vitalSignInfoListMap = (Map) vitalSignInfoBody.get("VitalSignInfoList");
            if (vitalSignInfoListMap.get("VitalSignInfo") instanceof ArrayList) {
                vitalSignInfoList = (List<Map>) vitalSignInfoListMap.get("VitalSignInfo");
            } else {
                vitalSignInfoList = new ArrayList<>();
                vitalSignInfoList.add((Map) vitalSignInfoListMap.get("VitalSignInfo"));
            }
            // 获取患者的身高和体重
            if (ObjectUtil.isNotNull(vitalSignInfoList) && vitalSignInfoList.size() > 0) {
                Map vitalSignInfoMap = vitalSignInfoList.get(0);
                // 身高
                String heightStr = String.valueOf(vitalSignInfoMap.get("height"));
                if (StringUtils.isNotBlank(heightStr)) {
                    patientBaseInfoVo.setPatientHeight(new BigDecimal(heightStr));
                    patientBaseInfo.setPatientHeight(new BigDecimal(heightStr));
                }
                // 体重
                String weightStr = String.valueOf(vitalSignInfoMap.get("Weight"));
                if (StringUtils.isNotBlank(weightStr)) {
                    patientBaseInfoVo.setPatientWeight(new BigDecimal(weightStr));
                    patientBaseInfo.setPatientWeight(new BigDecimal(weightStr));
                }
                // BMI=体重（kg）÷身高的平方（m）
                if (StringUtils.isNotBlank(heightStr) && StringUtils.isNotBlank(weightStr)) {
                    BigDecimal weight = new BigDecimal(weightStr);
                    BigDecimal heightPf = (new BigDecimal(heightStr).divide(new BigDecimal(100))).pow(2);
                    BigDecimal bmi = weight.divide(heightPf, 2, RoundingMode.UP);
                    patientBaseInfoVo.setPatientBmi(bmi);
                    patientBaseInfo.setPatientBmi(bmi);
                }
            }
        }
        // 更新患者信息
        baseMapper.updateById(patientBaseInfo);
        return patientBaseInfoVo;
    }

    /**
     * 查询患者基本信息列表
     */
    @Override
    public TableDataInfo<PatientBaseInfoVo> queryPageList(PatientBaseInfoBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PatientBaseInfo> lqw = buildQueryWrapper(bo);
        Page<PatientBaseInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询患者基本信息列表
     */
    @Override
    public List<PatientBaseInfoVo> queryList(PatientBaseInfoBo bo) {
        LambdaQueryWrapper<PatientBaseInfo> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 查询患者基本信息视图对象
     *
     * @param bo
     * @return
     */
    @Override
    public PatientBaseInfoVo queryOne(PatientBaseInfoBo bo) {
        PatientBaseInfoVo patientBaseInfoVo = baseMapper.selectVoOne(new LambdaQueryWrapper<PatientBaseInfo>()
            .eq(StringUtils.isNotBlank(bo.getPatientNo()), PatientBaseInfo::getPatientNo, bo.getPatientNo())
            .eq(StringUtils.isNotBlank(bo.getPaadmVisitNo()), PatientBaseInfo::getPaadmVisitNo, bo.getPaadmVisitNo())
            .eq(PatientBaseInfo::getPatientState, DictConstants.IN_PATIENT));
        return patientBaseInfoVo;
    }

    private LambdaQueryWrapper<PatientBaseInfo> buildQueryWrapper(PatientBaseInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PatientBaseInfo> lqw = Wrappers.lambdaQuery();
        lqw.like(bo.getMedicalRecordNo() != null, PatientBaseInfo::getMedicalRecordNo, bo.getMedicalRecordNo())
            .eq(bo.getDeptId() != null, PatientBaseInfo::getDeptId, bo.getDeptId())
            .like(StringUtils.isNotBlank(bo.getPatientName()), PatientBaseInfo::getPatientName, bo.getPatientName())
            .like(StringUtils.isNotBlank(bo.getPatientNo()), PatientBaseInfo::getPatientNo, bo.getPatientNo())
            .eq(StringUtils.isNotBlank(bo.getBedNo()), PatientBaseInfo::getBedNo, bo.getBedNo())
            .eq(StringUtils.isNotBlank(bo.getGuardianLevel()), PatientBaseInfo::getGuardianLevel, bo.getGuardianLevel())
            .eq(StringUtils.isNotBlank(bo.getPatientState()), PatientBaseInfo::getPatientState, bo.getPatientState())
            .eq(StringUtils.isNotBlank(bo.getPaadmVisitNo()), PatientBaseInfo::getPaadmVisitNo, bo.getPaadmVisitNo())
            .orderByAsc(PatientBaseInfo::getMedicalRecordNo);
        return lqw;
    }

    private Wrapper<PatientBaseInfo> buildQueryWrapper2(PatientBaseInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<PatientBaseInfo> qw = Wrappers.query();
        qw.like(ObjectUtil.isNotNull(bo.getMedicalRecordNo()), "pbi.medical_record_no", bo.getMedicalRecordNo())
            .like(StringUtils.isNotBlank(bo.getPatientName()), "pbi.patient_name", bo.getPatientName())
            .like(StringUtils.isNotBlank(bo.getPatientNo()), "pbi.patient_no", bo.getPatientNo())
            .like(StringUtils.isNotBlank(bo.getDoctorName()), "pbi.doctor_name", bo.getDoctorName())
            .like(StringUtils.isNotBlank(bo.getMedicareNo()), "pbi.medicare_no", bo.getMedicareNo())
            .eq(StringUtils.isNotBlank(bo.getBedNo()), "pbi.bed_no", bo.getBedNo())
            .eq(StringUtils.isNotBlank(bo.getGuardianLevel()), "pbi.guardian_level", bo.getGuardianLevel())
            .eq(StringUtils.isNotBlank(bo.getPatientState()), "pbi.patient_state", bo.getPatientState())
            .between(ObjectUtil.isNotNull(params.get("beginDate")) && ObjectUtil.isNotNull(params.get("endDate")), "pbi.discharge_time",
                params.get("beginDate") + " 00:00:00", params.get("endDate") + " 23:59:59")
            .and(ObjectUtil.isNotNull(bo.getDeptId()), w -> {
                List<SysDept> deptList = deptMapper.selectDeptList(new LambdaQueryWrapper<SysDept>()
                    .select(SysDept::getDeptId)
                    .apply(DataBaseHelper.findInSet(bo.getDeptId(), "ancestors")));
                List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
                ids.add(bo.getDeptId());
                w.in("pbi.dept_id", ids);
                w.or().isNull("pbi.dept_id");
            })
            .orderByAsc("pbi.guardian_level")
            .orderByDesc("pbi.medical_record_no");
        return qw;
    }

    private Wrapper<PatientBaseInfo> buildQueryWrapper3(PatientBaseInfoBo bo, String longDept) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<PatientBaseInfo> qw = Wrappers.query();
        qw.like(ObjectUtil.isNotNull(bo.getMedicalRecordNo()), "pbi.medical_record_no", bo.getMedicalRecordNo())
            .like(StringUtils.isNotBlank(bo.getPatientName()), "pbi.patient_name", bo.getPatientName())
            .like(StringUtils.isNotBlank(bo.getPatientNo()), "pbi.patient_no", bo.getPatientNo())
            .like(StringUtils.isNotBlank(bo.getMedicareNo()), "pbi.medicare_no", bo.getMedicareNo())
            .like(StringUtils.isNotBlank(bo.getDoctorName()), "pbi.doctor_name", bo.getDoctorName())
            .eq(StringUtils.isNotBlank(bo.getBedNo()), "pbi.bed_no", bo.getBedNo())
            .eq(StringUtils.isNotBlank(bo.getGuardianLevel()), "pbi.guardian_level", bo.getGuardianLevel())
            .eq(StringUtils.isNotBlank(bo.getPatientState()), "pbi.patient_state", bo.getPatientState())
            .isNotNull("sd.dept_name")
            .between(ObjectUtil.isNotNull(params.get("beginDate")) && ObjectUtil.isNotNull(params.get("endDate")), "pbi.discharge_time",
                params.get("beginDate") + " 00:00:00", params.get("endDate") + " 23:59:59")
            .and(StringUtils.isNotBlank(longDept), w -> {
                w.in("pbi.dept_id", longDept.split(","));
                w.or().isNull("pbi.dept_id");
            })
            .orderByAsc("pbi.guardian_level")
            .orderByDesc("pbi.medical_record_no");
        return qw;
    }

    /**
     * 构造处方审核查询对象
     *
     * @param bo
     * @return
     */
    private Wrapper<PatientBaseInfo> buildQueryWrapper4(PatientBaseInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<PatientBaseInfo> qw = Wrappers.query();
        // 病名不为空，根据病名查询药历号
        String illnessName = bo.getIllnessName();
        List<Integer> medicalRecordNoList = new ArrayList<>();
        if (StringUtils.isNotBlank(illnessName)) {
            List<HisAdmittingDiagInfo> hisAdmittingDiagInfoList = diagInfoMapper.selectList(new LambdaQueryWrapper<HisAdmittingDiagInfo>()
                .eq(HisAdmittingDiagInfo::getDiagCat, "中医")
                .like(HisAdmittingDiagInfo::getDiagDesc, illnessName)
                .select(HisAdmittingDiagInfo::getMedicalRecordNo));
            // 生成药历号List集合
            if (hisAdmittingDiagInfoList.size() > 0) {
                medicalRecordNoList = hisAdmittingDiagInfoList.stream().map(HisAdmittingDiagInfo::getMedicalRecordNo).collect(Collectors.toList());
            }
        }
        qw.isNotNull("pbi.paadm_visit_no")
            .in(bo.getDeptId() == null, "pbi.dept_id", new Long[]{1636619461641031681L, 1636619550568665089L, 1636619615890755586L})
            .eq(bo.getDeptId() != null, "dept_id", bo.getDeptId())
            .like(StringUtils.isNotBlank(bo.getMedicareNo()), "pbi.medicare_no", bo.getMedicareNo())
            .like(StringUtils.isNotBlank(bo.getPatientName()), "pbi.patient_name", bo.getPatientName())
            .like(StringUtils.isNotBlank(bo.getDoctorName()), "pbi.doctor_name", bo.getDoctorName())
            .in(medicalRecordNoList.size() > 0, "pbi.medical_record_no", medicalRecordNoList)
            .orderByDesc("pbi.medical_record_no");
        return qw;
    }

    /**
     * 新增患者基本信息
     */
    @Override
    public Boolean insertByBo(PatientBaseInfoBo bo) {
        PatientBaseInfo add = BeanUtil.toBean(bo, PatientBaseInfo.class);
        validEntityBeforeSave(add);
        // 生成病历号
        PatientBaseInfo patientBaseInfo = baseMapper.selectOne(new LambdaQueryWrapper<PatientBaseInfo>()
            .orderByDesc(PatientBaseInfo::getMedicalRecordNo)
            .last("limit 1"));
        if (ObjectUtil.isNull(patientBaseInfo)) {// 没有患者时给病历号赋初始值1001
            add.setMedicalRecordNo(1001);
        } else {// 已经存在患者时，病历号=最大病历号+1
            add.setMedicalRecordNo(patientBaseInfo.getMedicalRecordNo() + 1);
        }
        // 新增默认患者状态为住院
        add.setPatientState(DictConstants.IN_PATIENT);
        // 设置患者信息来源为手工录入
        add.setSourceInfo("0");
        // 设置默认监护级别为三级
        add.setGuardianLevel(DictConstants.GUARDIAN_LEVEL_ONE);
        // 设置就诊号码为manual
        if ("0".equals(bo.getSourceInfo())) {
            add.setPaadmVisitNo("manual");
        }
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改患者基本信息
     */
    @Override
    public Boolean updateByBo(PatientBaseInfoBo bo) {
        PatientBaseInfo update = BeanUtil.toBean(bo, PatientBaseInfo.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PatientBaseInfo entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除患者基本信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public TableDataInfo<PatientBaseInfoVo> queryPageListOfPatientInfo(PatientBaseInfoBo bo, PageQuery pageQuery) {
        // 查询住院状态列表
        List<SysDictData> stateList = dictDataMapper.selectDictDataByType(DictConstants.PATIENT_STATE_DICT_TYPE);
        Map<String, String> stateMap = stateList.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));

        // 获取登录用户对象
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            return TableDataInfo.fail("请登录");
        }

        SysUser sysUser = sysUserMapper.selectUserById(loginUser.getUserId());
        if (sysUser == null) {
            return TableDataInfo.fail("用户信息不存在");
        }

        // 获取登录用户角色
        List<String> roleKeyList = baseMapper.selectRoleKeyList(loginUser.getUserId());
        if (roleKeyList == null || roleKeyList.isEmpty()) {
            return TableDataInfo.fail("用户角色信息不存在");
        }

        Wrapper<PatientBaseInfo> lqw = buildQueryWrapperByRole(bo, sysUser, roleKeyList);

        if (lqw == null) {
            return TableDataInfo.fail("查询条件构建失败");
        }

        // 查询患者信息列表
        Page<PatientBaseInfoVo> result = baseMapper.customPageList(pageQuery.build(), lqw);

        // 住院状态设置字典标签
        if (result != null && result.getRecords() != null) {
            result.getRecords().forEach(patientBaseInfoVo -> {
                if (patientBaseInfoVo != null && patientBaseInfoVo.getPatientState() != null) {
                    patientBaseInfoVo.setPatientStateStr(stateMap.get(patientBaseInfoVo.getPatientState()));
                }
            });
        }

        return TableDataInfo.build(result);
    }

    /**
     * 根据用户角色构建查询条件
     *
     * @param bo 查询参数
     * @param sysUser 当前用户
     * @param roleKeyList 用户角色列表
     * @return 查询条件包装器
     */
    private Wrapper<PatientBaseInfo> buildQueryWrapperByRole(PatientBaseInfoBo bo, SysUser sysUser, List<String> roleKeyList) {
        if (bo == null || sysUser == null || roleKeyList == null || roleKeyList.isEmpty()) {
            return null;
        }

        // 按优先级处理角色：admin > quality > archiater > others(临床药师等)
        // 超级管理员权限最高
        if (roleKeyList.contains("admin")) {
            return buildQueryWrapper2(bo);
        }

        // 质检员
        if (roleKeyList.contains("quality")) {
            return buildQueryWrapper2(bo);
        }

        // 主任
        if (roleKeyList.contains("archiater")) {
            // 如果未指定科室，则使用主任所在科室
            if (bo.getDeptId() == null) {
                bo.setDeptId(sysUser.getDeptId());
            }
            return buildQueryWrapper2(bo);
        }

        // 临床药师等其他角色
        // 药师已经选择病区
        if (bo.getDeptId() != null) {
            return buildQueryWrapper2(bo);
        } else {
            // 查询药师常驻病区字符串
            String longDept = sysUser.getLongDept();
            // 如果药师没有常驻病区，限制查询范围为空
            if (StringUtils.isBlank(longDept)) {
                // 构建一个不返回任何结果的查询条件
                QueryWrapper<PatientBaseInfo> emptyWrapper = Wrappers.query();
                // 使用一个永远不成立的条件
                emptyWrapper.eq("1", "0");
                return emptyWrapper;
            }
            return buildQueryWrapper3(bo, longDept);
        }
    }

    /**
     * 出院
     *
     * @param id 患者ID
     * @return
     */
    @Override
    public R<Void> leave(Long id) {
        // 查询患者信息
        PatientBaseInfo patientBaseInfo = baseMapper.selectById(id);
        if (ObjectUtil.isNull(patientBaseInfo)) {
            return R.fail("患者不存在");
        }
        // 判断患者住院状态
        if (!DictConstants.IN_PATIENT.equals(patientBaseInfo.getPatientState())) {
            return R.fail("患者已出院");
        }
        // 改变患者住院状态为已出院
        patientBaseInfo.setPatientState(DictConstants.OUT_PATIENT);
        patientBaseInfo.setDischargeTime(LocalDateTime.now());
        // 更新转科记录
        HisChangeDepartmentBo hisChangeDepartmentBo = new HisChangeDepartmentBo();
        hisChangeDepartmentBo.setMedicalRecordNo(patientBaseInfo.getMedicalRecordNo());
        hisChangeDepartmentBo.setChangeOutTime(new Date());
        hisChangeDepartmentService.updateByBo(hisChangeDepartmentBo);
        return baseMapper.updateById(patientBaseInfo) > 0 ? R.ok("出院成功") : R.fail("出院失败");
    }

    /**
     * 查询历史药历
     *
     * @param medicalRecordNo 病历号
     * @param pageQuery       分页对象
     * @return
     */
    @Override
    public TableDataInfo<PatientBaseInfoVo> queryHistoryPageList(Integer medicalRecordNo, PageQuery pageQuery) {
        if (medicalRecordNo == null) {
            return TableDataInfo.fail("药历号不能为空");
        }
        // 查询患者ID号
        PatientBaseInfo patientBaseInfo = baseMapper.selectOne(new LambdaQueryWrapper<PatientBaseInfo>().eq(PatientBaseInfo::getMedicalRecordNo, medicalRecordNo));
        if (ObjectUtil.isNull(patientBaseInfo)) {
            return TableDataInfo.fail("患者不存在");
        }
        if (StringUtils.isBlank(patientBaseInfo.getPatientNo())) {
            return TableDataInfo.fail("患者ID号不存在");
        }
        String patientNo = patientBaseInfo.getPatientNo();
        // 根据患者ID号查询出院病历信息
        IPage<PatientBaseInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), new LambdaQueryWrapper<PatientBaseInfo>()
            .eq(PatientBaseInfo::getPatientNo, patientNo)
            .eq(PatientBaseInfo::getPatientState, DictConstants.OUT_PATIENT)
            .isNull(PatientBaseInfo::getMoveHistory)
            .select(PatientBaseInfo::getId, PatientBaseInfo::getPatientName, PatientBaseInfo::getAdmissionTime, PatientBaseInfo::getDischargeTime,
                PatientBaseInfo::getDoctorId, PatientBaseInfo::getMedicalRecordNo)
            .orderByDesc(PatientBaseInfo::getAdmissionTime, PatientBaseInfo::getDischargeTime));
        // 查询医生信息
        List<SysUser> sysUserList = sysUserMapper.selectVoList(new LambdaQueryWrapper<SysUser>().ne(SysUser::getUserName, "admin"));
        Map<Long, String> sysUserMap = sysUserList.stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName));
        // 设置主管医生姓名
        result.getRecords().stream().forEach(patientBaseInfoVo -> patientBaseInfoVo.setDoctorName(sysUserMap.get(patientBaseInfoVo.getDoctorId())));
        return TableDataInfo.build(result);
    }

    /**
     * 批量修改患者基本信息
     *
     * @param bo
     * @return
     */
    @Override
    public Boolean updateBatchByWrapper(PatientBaseInfoBo bo) {
        if (ObjectUtil.isNull(bo)) {
            return false;
        }
        if (StringUtils.isBlank(bo.getPatientNo())) {
            return false;
        }
        PatientBaseInfo patientBaseInfo = BeanUtil.toBean(bo, PatientBaseInfo.class);
        return baseMapper.update(patientBaseInfo, new LambdaQueryWrapper<PatientBaseInfo>().eq(PatientBaseInfo::getPatientNo, bo.getPatientNo())) > 0;
    }

    /**
     * 查询患者病历号
     *
     * @param medicalRecordNo 病历号
     * @return
     */
    @Override
    public R<String> queryGuardianLevel(Integer medicalRecordNo) {
        PatientBaseInfoVo patientBaseInfoVo = baseMapper.selectVoOne(new LambdaQueryWrapper<PatientBaseInfo>().eq(PatientBaseInfo::getMedicalRecordNo, medicalRecordNo));
        String guardianLevel = null;
        if (ObjectUtil.isNotNull(patientBaseInfoVo)) {
            guardianLevel = patientBaseInfoVo.getGuardianLevel();
        }
        return R.ok("查询成功", guardianLevel);
    }

    /**
     * 查询患者病症信息列表
     *
     * @param bo
     * @param pageQuery
     * @return
     */
    @Override
    public TableDataInfo<PatientBaseInfoVo> getPatientBaseInfoListOfTcm(PatientBaseInfoBo bo, PageQuery pageQuery) {
        // 查询中药饮片处方审核患者列表
        Page<PatientBaseInfoVo> result = baseMapper.getPatientBaseInfoListOfTcm(pageQuery.build(), buildQueryWrapper4(bo));
        List<Integer> medicalRecordNoList = new ArrayList<>();
        result.getRecords().stream().forEach(patientBaseInfoVo -> {
            patientBaseInfoVo.setDiagFlag("1");
            medicalRecordNoList.add(patientBaseInfoVo.getMedicalRecordNo());
        });
        // 查询诊断信息
        if (medicalRecordNoList.size() > 0) {
            List<HisAdmittingDiagInfoVo> diagInfoVoList = diagInfoMapper.selectVoList(new LambdaQueryWrapper<HisAdmittingDiagInfo>()
                .eq(HisAdmittingDiagInfo::getDiagType, "3")
                .in(HisAdmittingDiagInfo::getDiagCat, new String[]{"中医", "证型"})
                .in(HisAdmittingDiagInfo::getMedicalRecordNo, medicalRecordNoList));
            Map<Integer, List<HisAdmittingDiagInfoVo>> diagMap = diagInfoVoList.stream().collect(Collectors.groupingBy(HisAdmittingDiagInfoVo::getMedicalRecordNo));

            // 设置处方审核病症按钮显示的标识
            result.getRecords().stream().forEach(patientBaseInfoVo -> {
                if (diagMap.get(patientBaseInfoVo.getMedicalRecordNo()) != null) {
                    patientBaseInfoVo.setDiagFlag("0");
                }
            });
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询病症集合
     *
     * @param medicalRecordNo 流水号
     * @param diagType        诊断类型（2出院诊断 3入院诊断）
     * @return
     */
    @Override
    public R<Map<String, List<String>>> getIllnessAndSymptomByMedicalRecordNo(Integer medicalRecordNo, String diagType) {
        // 创建返回Map
        Map<String, List<String>> diagMap = new ListOrderedMap<>();
        try {
            // 查询患者诊断信息
            List<HisAdmittingDiagInfo> diagInfoList = diagInfoMapper.selectList(new LambdaQueryWrapper<HisAdmittingDiagInfo>()
                .eq(HisAdmittingDiagInfo::getMedicalRecordNo, medicalRecordNo)
                .eq(HisAdmittingDiagInfo::getDiagType, diagType)
                .in(HisAdmittingDiagInfo::getDiagCat, new String[]{"中医", "证型"}));
            if (diagInfoList.size() > 0) {
                List<HisAdmittingDiagInfo> illnessNameList = diagInfoList.stream().filter(hisAdmittingDiagInfo -> StringUtils.equals(hisAdmittingDiagInfo.getDiagCat(), "中医")).collect(Collectors.toList());
                illnessNameList.stream().forEach(hisAdmittingDiagInfo -> {
                    boolean flag = false;
                    int num = 0;
                    List<String> symptomNameList = new ArrayList<>();
                    for (int i = 0; i < diagInfoList.size(); i++) {
                        if (StringUtils.equals(diagInfoList.get(i).getDiagCat(), "中医")
                            && StringUtils.equals(hisAdmittingDiagInfo.getDiagDesc(), diagInfoList.get(i).getDiagDesc())) {
                            flag = true;
                            num++;
                        } else if (StringUtils.equals(diagInfoList.get(i).getDiagCat(), "中医")
                            && !StringUtils.equals(hisAdmittingDiagInfo.getDiagDesc(), diagInfoList.get(i).getDiagDesc())) {
                            flag = false;
                        }
                        if (StringUtils.equals(diagInfoList.get(i).getDiagCat(), "证型") && flag) {
                            symptomNameList.add(diagInfoList.get(i).getDiagDesc());
                        }
                    }
                    diagMap.put(hisAdmittingDiagInfo.getDiagDesc(), symptomNameList.stream().distinct().collect(Collectors.toList()));
                });
            }
            return R.ok("查询成功", diagMap);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return R.fail("查询失败");
        }
    }

    /**
     * 获取不良反应参数拼接字符串
     *
     * @param userId 用户id
     * @return
     */
    @Override
    public R<String> getAdrParams(Long userId) {
        String orgCode = "0022"; // 医院代码
        String signKey = "vfawfvksz4kp22htn3umx484gde6dsdg"; // 签名密钥
        // 查询用户的信息
        SysUser sysUser = sysUserMapper.selectUserById(userId);
        String hisUserNo = sysUser.getHisUserNo(); // 用户HIS员工工号
        if (StringUtils.isBlank(hisUserNo)) {
            return R.fail("用户没有设置HIS工号");
        }
        // 查询用户科室信息
        SysDept dept = sysUser.getDept();
        if (ObjectUtil.isNull(dept)) {
            return R.fail("科室信息不存在");
        } else if (StringUtils.isBlank(dept.getHisDeptCode())) {
            return R.fail("科室没有设置HIS代码");
        }
        String hisDeptCode = dept.getHisDeptCode(); // 科室的HIS代码
        // 时间戳
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String timestamp = format.format(new Date());
        // 计算签名值
        String paramStr = "orgCode=" + orgCode + "&staffCode=" + hisUserNo + "&deptCode=" + hisDeptCode + "&timestamp=" + timestamp + "&signKey=" + signKey;
        String sign = SecureUtil.md5(paramStr);
        // 拼接参数链接字符串
        paramStr = "orgCode=" + orgCode + "&staffCode=" + hisUserNo + "&deptCode=" + hisDeptCode + "&timestamp=" + timestamp + "&sign=" + sign;
        return R.ok("获取成功", paramStr);
    }
}
